home *** CD-ROM | disk | FTP | other *** search
- /*
- Copyright (c) 1991-1999 Amiga, Inc.
-
- This example is provided in electronic form by Amiga, Inc.
- for use with the Amiga Mail Volume II technical publication.
- Amiga Mail Volume II contains additional information on the correct
- usage of the techniques and operating system functions presented in
- these examples. The source and executable code of these examples may
- only be distributed in free electronic form, via bulletin board or
- as part of a fully non-commercial and freely redistributable
- diskette. Both the source and executable code (including comments)
- must be included, without modification, in any copy. This example
- may not be published in printed form or distributed with any
- commercial product. However, the programming techniques and support
- routines set forth in these examples may be used in the development
- of original executable software products for Amiga
- computers.
-
- All other rights reserved.
-
- This example is provided "as-is" and is subject to change; no
- warranties are made. All use is at your own risk. No liability or
- responsibility is assumed.
- *
- * Written by David N. Junod
- *
- * Compiled with SAS/C 6.56 sc NMINC STRMERGE OPTSIZE OPTIMIZE OPTGLOBAL NOSTKCHK
- * (must be linked with classface.o and hookface.o)
- *
- * The Image structure as used by this class:
- *
- * struct Image {
- *
- * SHORT LeftEdge; <----Offset relative to the container
- * SHORT TopEdge;
- *
- * SHORT Width; <----Contains the text extent of the string
- * SHORT Height;
- *
- * SHORT Depth; <----Maintained by boopsi (must be set to CUSTOMIMAGEDEPTH).
- *
- * USHORT *ImageData; <----Pointer to a NULL terminated text string
- *
- * UBYTE PlanePick; <----We use this for the foreground color
- *
- * UBYTE PlaneOnOff; <----We use this for the background color
- *
- * struct Image *NextImage; <----Pointer to the next image. Handled by DrawImage(). };
- */
-
-
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <exec/libraries.h>
- #include <intuition/intuition.h>
- #include <intuition/classes.h>
- #include <intuition/classusr.h>
- #include <intuition/cghooks.h>
- #include <intuition/gadgetclass.h>
- #include <intuition/imageclass.h>
- #include <intuition/icclass.h>
- #include <intuition/screens.h>
- #include <graphics/gfx.h>
- #include <graphics/gfxmacros.h>
- #include <libraries/gadtools.h>
- #include <utility/tagitem.h>
- #include <clib/macros.h>
- #include <clib/exec_protos.h>
- #include <clib/intuition_protos.h>
- #include <clib/graphics_protos.h>
- #include <clib/utility_protos.h>
- #include <string.h>
-
- extern struct Library *SysBase, *DOSBase;
- extern struct Library *IntuitionBase, *GfxBase, *UtilityBase;
-
- /*
- * Because we are dealing with imageclass objects, the data structure that makes up the
- * object is an intuition Image structure.
- */
- #define IM(o) ((struct Image *)(o))
-
- #define MYCLASSID NULL
- #define SUPERCLASSID (IMAGECLASS)
-
- Class *initmyTextLabelClass(VOID);
- ULONG freemyTextLabelClass(Class * cl);
- ULONG __saveds dispatchmyTextLabel(Class * cl, Object * o, Msg msg);
- ULONG setmyTextLabelAttrs(Class * cl, Object * o, struct opSet * msg);
- ULONG getmyTextLabelAttr(Class * cl, Object * o, struct opGet * msg);
- ULONG drawmyTextLabel(Class * cl, Object * o, struct impDraw * msg);
- WORD aTextExtent(struct RastPort *, STRPTR, LONG, struct TextExtent *);
- UWORD GetLabelKeystroke(STRPTR label);
- static VOID getContentsExtent(Class * cl, Object * o, struct DrawInfo * drinfo);
-
- /* prototypes of functions from classface.o */
- ULONG DoMethod(Object * o, ULONG methodID,...);
- ULONG DoSuperMethod(Class * cl, Object * o, ULONG methodID,...);
- ULONG CoerceMethod(Class * cl, Object * o, ULONG methodID,...);
- ULONG CM(Class * cl, Object * o, Msg msg);
- ULONG DM(Object * o, Msg msg);
- ULONG DSM(Class * cl, Object * o, Msg msg);
- ULONG SetSuperAttrs(Class * cl, Object * o, ULONG data,...);
-
- struct localObjData
- {
- /* Font to use */
- struct TextFont *lod_Font;
-
- /* The key that is underlined */
- UWORD lod_Key;
-
- /* DrawMode */
- UBYTE lod_Mode;
- };
-
-
- Class *
- initmyTextLabelClass(VOID)
- {
- ULONG hookEntry(); /* from hookface.o */
- Class *cl;
-
- if (cl = MakeClass(MYCLASSID,
- SUPERCLASSID, NULL,
- sizeof(struct localObjData), 0))
- {
- /* Fill in the callback hook */
- cl->cl_Dispatcher.h_Entry = hookEntry;
- cl->cl_Dispatcher.h_SubEntry = dispatchmyTextLabel;
- }
- /* Return a pointer to the class */
- return (cl);
- }
-
-
- ULONG
- freemyTextLabelClass(Class * cl)
- {
-
- /* Try to free the public class */
- return ((ULONG) FreeClass(cl));
- }
-
-
- /*
- * The SAS "__saveds" flag tells the SAS compiler to put
- * the data storage address + 32766 into A4.
- */
- ULONG __saveds
- dispatchmyTextLabel(Class * cl, Object * o, Msg msg)
- {
- struct localObjData *lod;
- Object *newobj;
- ULONG retval;
-
- switch (msg->MethodID)
- {
- case OM_NEW:
- /* Pass up to the superclass... */
- if (newobj = (Object *) DSM(cl, o, msg))
- {
- struct TagItem *attrs = ((struct opSet *) msg)->ops_AttrList;
- struct DrawInfo *drinfo;
-
- /* Get the DrawInfo */
- drinfo = (struct DrawInfo *) GetTagData(SYSIA_DrawInfo, NULL, attrs);
-
- /* Get the instance data */
- lod = INST_DATA(cl, newobj);
-
- /* Establish defaults */
- IM(newobj)->PlanePick = 1;
- lod->lod_Mode = JAM1;
-
- /* Set the attributes */
- setmyTextLabelAttrs(cl, newobj, (struct opSet *) msg);
-
- /* Get the bounding rectangle of the label */
- getContentsExtent(cl, newobj, drinfo);
- }
- retval = (ULONG) newobj;
- break;
-
- case OM_GET:
- retval = getmyTextLabelAttr(cl, o, (struct opGet *) msg);
- break;
-
- case OM_UPDATE:
- case OM_SET:
- /* Do the superclass first */
- retval = DSM(cl, o, msg);
-
- /* Call our set routines */
- retval += setmyTextLabelAttrs(cl, o, (struct opSet *) msg);
- break;
-
- case IM_DRAW: /* draw the label */
- case IM_DRAWFRAME: /* drawmyTextLabel() will take care of
- extra framing info */
- retval = drawmyTextLabel(cl, o, (struct impDraw *) msg);
- break;
-
- /* Let the superclass handle everything else */
- default:
- retval = (ULONG) DSM(cl, o, msg);
- break;
- }
-
- return (retval);
- }
-
-
- /* Set attributes of an object */
- ULONG
- setmyTextLabelAttrs(Class * cl, Object * o, struct opSet * msg)
- {
- struct localObjData *lod = INST_DATA(cl, o);
- struct TagItem *tags = msg->ops_AttrList;
- struct TagItem *tstate;
- struct TagItem *tag;
- ULONG tidata;
-
- /* process rest */
- tstate = tags;
- while (tag = NextTagItem(&tstate))
- {
- tidata = tag->ti_Data;
- switch (tag->ti_Tag)
- {
- case IA_FGPen:
- IM(o)->PlanePick = (UBYTE) tidata;
- break;
-
- case IA_BGPen:
- IM(o)->PlaneOnOff = (UBYTE) tidata;
- break;
-
- /* Must be a TextFont pointer. */
- case IA_Font:
- /* Set the font */
- lod->lod_Font = (struct TextFont *) tidata;
- break;
-
- /* Drawing mode to use */
- case IA_Mode:
- lod->lod_Mode = (UBYTE) tidata;
- break;
-
- case IA_Data:
- IM(o)->ImageData = (USHORT *) tidata;
- lod->lod_Key = GetLabelKeystroke((STRPTR) tidata);
- break;
- }
- }
-
- return (1L);
- }
-
-
-
-
-
-
- /* Inquire attributes of an object */
- ULONG
- getmyTextLabelAttr(Class * cl, Object * o, struct opGet * msg)
- {
- struct localObjData *lod = INST_DATA(cl, o);
-
- switch (msg->opg_AttrID)
- {
- case IA_Font:
- *msg->opg_Storage = (ULONG) lod->lod_Font;
- break;
-
- case IA_Mode:
- *msg->opg_Storage = (ULONG) lod->lod_Mode;
- break;
-
- /* Let the superclass try */
- default:
- return ((ULONG) DSM(cl, o, msg));
- }
-
- return (1L);
- }
-
-
- ULONG
- drawmyTextLabel(Class * cl, Object * o, struct impDraw * msg)
- {
- struct localObjData *lod = INST_DATA(cl, o);
- STRPTR label = (STRPTR) IM(o)->ImageData;
- struct DrawInfo *di = msg->imp_DrInfo;
- struct RastPort *rp = msg->imp_RPort;
- struct TextFont *tf = NULL;
- WORD len = strlen(label);
- WORD left, top;
- WORD height = 0;
- WORD width = 0;
- WORD i;
-
- /* Clear the key */
- lod->lod_Key = NULL;
-
- /* Get a pointer to the font to use */
- if (!(tf = lod->lod_Font) && di)
- {
- tf = di->dri_Font;
- }
-
- /* Make sure we have font pointer */
- if (tf)
- {
- /* Set the font */
- SetFont(rp, tf);
- }
- /* Figure out our coordinates */
- top = msg->imp_Offset.Y + IM(o)->TopEdge + rp->TxBaseline;
- left = msg->imp_Offset.X + IM(o)->LeftEdge;
-
- /* See if we have frame information. */
- if (msg->MethodID == IM_DRAWFRAME)
- {
- /* Center the text inside the frame. */
- width = msg->imp_Dimensions.Width;
- height = msg->imp_Dimensions.Height;
- top += ((height - IM(o)->Height) > 0) ? ((height - IM(o)->Height) / 2) : 0;
- left += ((width - IM(o)->Width) > 0) ? ((width - IM(o)->Width) / 2) : 0;
- }
-
- /* Set the colors */
- SetAPen(rp, IM(o)->PlanePick);
- SetBPen(rp, IM(o)->PlaneOnOff);
-
- /* Set the drawing mode */
- SetDrMd(rp, lod->lod_Mode);
-
- /* Move to the start */
- Move(rp, left, top);
-
-
-
- /* Step through string */
- for (i = 0; i < (len - 1); i++)
- {
- /* Is this an '_' ? */
- if (label[i] == '_')
- {
- WORD bot = (top + rp->TxHeight - rp->TxBaseline);
- WORD mark;
-
- /* Draw the first part of the string */
- Text(rp, label, i);
-
- /* Remember where we are in the string */
- mark = rp->cp_x;
-
- /* Draw the underscore */
- Move(rp, mark, bot);
- Draw(rp, (mark + TextLength(rp, &label[(i + 1)], 1L) - 2), bot);
-
- /* Return to where we were */
- Move(rp, mark, top);
-
- /*
- * Draw the rest of the string. This one is done last so that the cursor
- * could be positioned after the text.
- */
- Text(rp, &label[(i + 1)], (len - i - 1));
-
- /* Return the underlined character */
- lod->lod_Key = (UWORD) label[i];
- }
- }
-
- /* Do we have an underscore? */
- if (!lod->lod_Key)
- {
- /* Didn't find an '_' sign */
- Text(rp, label, len);
- }
- return (1L);
- }
-
-
- UWORD
- GetLabelKeystroke(STRPTR label)
- {
- LONG count = (label) ? strlen(label) : 0L;
- LONG i;
-
- /* Search for an _ sign */
- for (i = 0; i < (count - 1); i++)
- {
- /* Did we find an _ sign? */
- if (label[i] == '_')
- {
- return ((UWORD) label[(i + 1)]);
- }
- }
-
- return (0);
- }
-
-
- /* TextExtent that honors the '_' as being a non-printable character (once) */
- WORD
- aTextExtent(struct RastPort * rp, STRPTR string, LONG count, struct TextExtent * te)
- {
- WORD retval = FALSE;
- STRPTR buffer;
- LONG i;
-
- /* Allocate a temporary buffer */
- if (buffer = AllocVec ((count + 1), MEMF_CLEAR))
- {
- /* Step through string */
- for (i = 0; i < count; i++)
- {
- /* Is this an '_' sign? */
- if (string[i] == '_')
- {
- /* Add the rest of the label to the buffer */
- strcat (buffer, &string[(i + 1)]);
-
- /* Adjust the length of the string. */
- count--;
- break;
- }
- else
- {
- /* Copy each character over, until we reach the _ mark */
- buffer[i] = string[i];
- }
- }
-
- /* Get the extent */
- TextExtent(rp, buffer, count, te);
-
- /* Free the temporary buffer */
- FreeVec (buffer);
-
- /* Show that we were successful */
- retval = TRUE;
- }
-
- /* Return whatever textextent returned */
- return (retval);
- }
-
- static VOID
- getContentsExtent(Class * cl, Object * o, struct DrawInfo * drinfo)
- {
- struct localObjData *lod = INST_DATA(cl, o);
- struct TextExtent te =
- {NULL};
- struct RastPort rp;
- STRPTR label;
-
- /* maybe look at some flags to handle other types of text someday */
- if (label = (STRPTR) IM(o)->ImageData)
- {
- /* Initialize the RastPort */
- InitRastPort(&rp);
-
- if (lod->lod_Font)
- {
- SetFont(&rp, lod->lod_Font);
- }
- else if (drinfo && drinfo->dri_Font)
- {
- SetFont(&rp, drinfo->dri_Font);
- }
- /* Get the rectangle for the label */
- aTextExtent(&rp, label, strlen(label), &te);
-
- /* Set the image structure */
- IM(o)->Width = te.te_Width;
- IM(o)->Height = te.te_Height;
- }
- else
- {
- IM(o)->Width = IM(o)->Height = 0;
- }
- }
-